from flask import Flask, request, render_template,jsonify
import pandas as pd
import random
from flask_sqlalchemy import SQLAlchemy
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.decomposition import TruncatedSVD
import os
import data_loader

app = Flask(__name__)

data_loader.main()



# load files===========================================================================================================
iteam_data = pd.read_csv('iteam_data_final.csv')

trending_products = pd.read_csv("cleaned_trending_products.csv")
train_data = pd.read_csv("train_data2.csv")
 
# database configuration---------------------------------------
app.secret_key = "alskdjfwoeieiurlskdjfslkdjf"
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://root:Wyytyks_158425@localhost/ecom"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

def find(iteam_id):
    return train_data[train_data["ID"]==iteam_id]['ImageURL'].values[0]
def change(user_name):
    if len(iteam_data[iteam_data['username']==user_name]['visitorid'].values)!=0:
        return int (iteam_data[iteam_data['username']==user_name]['visitorid'].values[0])
    else:
        return 0
def change_list(list1):
    m  = train_data[train_data["ID"].isin(list1)]
    return m[['Name','ReviewCount', 'Brand', 'ImageURL', 'Rating']]

print(change('VcpJa6eC'))  
     
# Define the unified 'User' table,用户注册和登录
# Define your model class for the 'signup' table
class Signup(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(100), nullable=False)
    password = db.Column(db.String(100), nullable=False)

# Define your model class for the 'signup' table
class Signin(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(100), nullable=False)
    password = db.Column(db.String(100), nullable=False)

# Recommendations functions============================================================================================
# Function to truncate product name
def truncate(text, length):
    if len(text) > length:
        return text[:length] + "..."
    else:
        return text
##推荐算法1
def recommend_list1(df,user_id):
    user_item_matrix = df.pivot(index='visitorid', columns='itemid', values='score').fillna(0)
    # 计算物品相似度矩阵
    item_similarity = cosine_similarity(user_item_matrix.T)
    item_similarity_df = pd.DataFrame(item_similarity, index=user_item_matrix.T.index, columns=user_item_matrix.T.index)
    # 定义推荐函数
    def item_based_recommendation(user_id, top_n=6):
        user_ratings = user_item_matrix.loc[user_id]
        similar_items = item_similarity_df.dot(user_ratings)
        similar_items = similar_items.sort_values(ascending=False)
        already_interacted = user_ratings[user_ratings > 0].index
        recommended_items = similar_items.drop(already_interacted).head(top_n)
        return recommended_items

    user_id_example = user_id
    recommendations = item_based_recommendation(user_id_example)
    return list(recommendations.index)

##推荐算法2
def recommend_list2(df,user_id):
    user_item_matrix = df.pivot(index='visitorid', columns='itemid', values='score').fillna(0)
    # 使用 SVD 进行矩阵分解
    svd = TruncatedSVD(n_components=10)
    user_matrix = svd.fit_transform(user_item_matrix)
    item_matrix = svd.components_.T
    # 预测评分
    predicted_ratings = user_matrix @ item_matrix.T
    # 定义推荐函数
    def svd_recommendation(user_id, top_n=6):
        user_ratings = predicted_ratings[user_id]
        top_item_indices = user_ratings.argsort()[::-1][:top_n]
        top_items = user_item_matrix.columns[top_item_indices]
        return top_items
    user_id_example =user_id
    recommendations = svd_recommendation(user_id_example)
    print(recommendations)
    return list(recommendations)
    


##推荐算法3
def content_based_recommendations(train_data, item_name, top_n=10):
    if item_name not in train_data['Name'].values:
        print(f"Item '{item_name}' not found in the training data.")
        return pd.DataFrame()

    tfidf_vectorizer = TfidfVectorizer(stop_words='english')
    tfidf_matrix_content = tfidf_vectorizer.fit_transform(train_data['Tags'])

    cosine_similarities_content = cosine_similarity(tfidf_matrix_content, tfidf_matrix_content)
    item_index = train_data[train_data['Name'] == item_name].index[0]

    similar_items = list(enumerate(cosine_similarities_content[item_index]))

    similar_items = sorted(similar_items, key=lambda x: x[1], reverse=True)

    top_similar_items = similar_items[1:top_n+1]

    recommended_item_indices = [x[0] for x in top_similar_items]
    recommended_items_details = train_data.iloc[recommended_item_indices][['Name', 'ReviewCount', 'Brand', 'ImageURL', 'Rating']]
    return recommended_items_details
# routes===============================================================================
# List of predefined image URLs
image_urls = [
    "static/img/img_1.png",
    "static/img/img_2.png",
    "static/img/img_3.png",
    "static/img/img_4.png",
    "static/img/img_5.png",
    "static/img/img_6.png",
    "static/img/img_7.png",
    "static/img/img_8.png",
]
recommend_price = [50,80,40,60,20,10,90,30]

@app.route("/")
def index():
    # Create a list of random image URLs for each product
    product_image_urls = image_urls
    price = recommend_price
    return render_template('index.html',trending_products=trending_products.head(8),truncate = truncate,
                           random_product_image_urls=product_image_urls,
                           random_price = price)

@app.route("/main")
def main():
    return render_template('main.html')

@app.route("/cart")
def cartdirect():
    # Create a list of random image URLs for each product
    pro = pd.read_csv('pros.csv')
    image = pro['image']
    return render_template("cart.html",trending_products = pro ,truncate=truncate,random_product_image_urls =image )

@app.route('/add_to_cart', methods=['POST'])
def add_to_cart():
    def append_df_to_csv(df, csv_file_path):
        try:
            # 尝试读取现有的 CSV 文件
            existing_df = pd.read_csv(csv_file_path)
            # 将新的 DataFrame 追加到现有 DataFrame 的末尾
            combined_df = pd.concat([existing_df, df], ignore_index=True)
            # 保存合并后的 DataFrame 到 CSV 文件
            combined_df.to_csv(csv_file_path, index=False)
            print(f"DataFrame has been appended to {csv_file_path}")
        except FileNotFoundError:
            # 如果文件不存在，直接将 DataFrame 保存为 CSV 文件
            df.to_csv(csv_file_path, index=False)
            print(f"DataFrame has been saved to {csv_file_path}")    
    # 确保前端发送的是 POST 请求并且请求体是 JSON 格式
    product = request.json  # 直接获取 JSON 数据
    print(product)
    pro = pd.DataFrame([product])
    if os.path.exists('pros.csv'):
        append_df_to_csv(pro,'pros.csv')
    else:
        pro.to_csv('pros.csv')
    return jsonify({'message': 'Product added to cart successfully'})
   
        
        


# routes
@app.route("/index")
def indexredirect():
    # Create a list of random image URLs for each product
    random_product_image_urls = [random.choice(image_urls) for _ in range(len(trending_products))]
    price = [40, 50, 60, 70, 100, 122, 106, 50, 30, 50]
    return render_template('index.html', trending_products=trending_products.head(8), truncate=truncate,
                           random_product_image_urls=random_product_image_urls,
                           random_price=random.choice(price))

@app.route("/signup", methods=['POST','GET'])
def signup():
    if request.method=='POST':
        username = request.form['username']
        email = request.form['email']
        password = request.form['password']

        new_signup = Signup(username=username, email=email, password=password)
        db.session.add(new_signup)
        db.session.commit()

        # Create a list of random image URLs for each product
        random_product_image_urls = [random.choice(image_urls) for _ in range(len(trending_products))]
        price = [40, 50, 60, 70, 100, 122, 106, 50, 30, 50]
        return render_template('index.html', trending_products=trending_products.head(8), truncate=truncate,
                               random_product_image_urls=random_product_image_urls, random_price=random.choice(price),
                               signup_message='User signed up successfully!'
                               )

# Route for signup page
@app.route('/signin', methods=['POST', 'GET'])
def signin():
    if request.method == 'POST':
        username = request.form['signinUsername']
        password = request.form['signinPassword']
        new_signup = Signin(username=username,password=password)
        db.session.add(new_signup)
        db.session.commit()
        if change(username)==0:
            random_product_image_urls=image_urls
            price = [41,56,78,89,70,89,56,57,67,68,78,79]
            return render_template('index.html', trending_products=trending_products.head(8), truncate=truncate,
                               random_product_image_urls=random_product_image_urls, random_price=random.choice(price),
                               signup_message='User signed up successfully!'
                               )
        else:
            recommend_list= recommend_list2(iteam_data,change(username))
            recommend_list+=recommend_list1(iteam_data,change(username))

            
            #for x in recommend_list:
                #recommend_image_urls.append(find(x))
            # Create a list of random image URLs for each product
            #random_product_image_urls = [recommend_image_urls for _ in range(12)]
            price = [41,56,78,89,70,89,56,57,67,68,78,79]
            product_recommend = change_list(recommend_list)
            product_recommend.to_csv("pro.csv")
            final_product_recommend = pd.read_csv("pro.csv")
            recommend_image_urls = final_product_recommend['ImageURL'] 
            if len(recommend_image_urls)==0:
                recommend_image_urls = image_urls
            return render_template('index.html', trending_products=final_product_recommend, truncate=truncate,
                                random_product_image_urls=recommend_image_urls, random_price=price,
                                signup_message='User signed in successfully!'
                                )

        

@app.route("/recommendations", methods=['POST', 'GET'])
def recommendations():
    if request.method == 'POST':
        prod = request.form.get('prod')
        nbr = int(request.form.get('nbr'))
        content_based_rec = content_based_recommendations(train_data, prod, top_n=nbr)

        if content_based_rec.empty:
            message = "No recommendations available for this product."
            return render_template('main.html', message=message)
        else:
            # Create a list of random image URLs for each recommended product
            random_product_image_urls = [random.choice(image_urls) for _ in range(len(trending_products))]
            print(content_based_rec)
            print(random_product_image_urls)

            price = [40, 50, 60, 70, 100, 122, 106, 50, 30, 50]
            return render_template('main.html', content_based_rec=content_based_rec, truncate=truncate,
                                   random_product_image_urls=random_product_image_urls,
                                   random_price=random.choice(price))


if __name__=='__main__':
    app.run(debug=True)



    